﻿using SlamDunk.MES.Domain.Entities.DefinitionContext;
using SlamDunk.MES.Domain.Entities.ExecutionContext;
using SlamDunk.MES.Domain.Entities.PlanContxt;
using SlamDunk.MES.Domain.IDomainServices;
using SlamDunk.MES.Domain.Mediators;
using SlamDunk.ValueObjects.Enums;
using System;
using System.Collections.Generic;

namespace SlamDunk.MES.DomainService.Implements
{
    /// <summary>
    /// 工单领域服务实现
    /// </summary>
    public class WorkOrderService : IWorkOrderService
    {
        #region # 字段及构造器

        /// <summary>
        /// 仓储中介者
        /// </summary>
        private readonly RepositoryMediator _repMediator;

        /// <summary>
        /// 依赖注入构造器
        /// </summary>
        public WorkOrderService(RepositoryMediator repMediator)
        {
            this._repMediator = repMediator;
        }

        #endregion

        #region # 生成工单 —— ICollection<WorkOrder> GenerateWorkOrders(ExecutionPlan executionPlan)
        /// <summary>
        /// 生成工单
        /// </summary>
        /// <param name="executionPlan">作业计划</param>
        /// <returns>工单列表</returns>
        public ICollection<WorkOrder> GenerateWorkOrders(ExecutionPlan executionPlan)
        {
            #region # 验证

            if (executionPlan.CheckStatus != CheckStatus.Passed)
            {
                throw new InvalidOperationException("作业计划未审核通过，不可生成工单！");
            }

            #endregion

            Process process = this._repMediator.ProcessRep.Single(executionPlan.ProcessId);

            IList<WorkOrder> workOrders = new List<WorkOrder>();
            foreach (ProcessSegment processSegment in process.Segments)
            {
                string workOrderNo = $"{executionPlan.Number}-{processSegment.Sort:D2}";
                long durationQuotaTicks = (long)Math.Ceiling(processSegment.DurationQuotaTicks * executionPlan.ExpGrossQuantity / process.RunSize);
                WorkOrder workOrder = new WorkOrder(workOrderNo, processSegment.Name, executionPlan.ProductionPlanId, executionPlan.Id, processSegment.Id, TimeSpan.FromTicks(durationQuotaTicks), processSegment.DirectivePath, processSegment.FacilityId, processSegment.WorkStationId, processSegment.FormMode, processSegment.FormDefinition, processSegment.NeedToInspect, processSegment.Sort, processSegment.Description);

                //工单人员要求
                IList<WorkOrderPersonAsk> personAsks = new List<WorkOrderPersonAsk>();
                foreach (SegmentPersonRule personRule in processSegment.PersonRules)
                {
                    WorkOrderPersonAsk personAsk = new WorkOrderPersonAsk(personRule.PersonClassId, personRule.PersonId, personRule.PersonUse, personRule.Quantity, personRule.FacilityId, personRule.Sort, personRule.Description);
                    personAsks.Add(personAsk);
                }
                //工单设备要求
                IList<WorkOrderEquipmentAsk> equipmentAsks = new List<WorkOrderEquipmentAsk>();
                foreach (SegmentEquipmentRule equipmentRule in processSegment.EquipmentRules)
                {
                    WorkOrderEquipmentAsk equipmentAsk = new WorkOrderEquipmentAsk(equipmentRule.EquipmentClassId, equipmentRule.EquipmentId, equipmentRule.EquipmentUse, equipmentRule.Quantity, equipmentRule.FacilityId, equipmentRule.Sort, equipmentRule.Description);
                    equipmentAsks.Add(equipmentAsk);
                }
                //工单物料要求
                IList<WorkOrderMaterialAsk> materialAsks = new List<WorkOrderMaterialAsk>();
                foreach (SegmentMaterialRule materialRule in processSegment.MaterialRules)
                {
                    decimal? quantity = null;
                    if (materialRule.Quantity.HasValue)
                    {
                        quantity = materialRule.Quantity.Value * executionPlan.ExpGrossQuantity / process.RunSize;
                    }

                    WorkOrderMaterialAsk materialAsk = new WorkOrderMaterialAsk(materialRule.MaterialId, null, materialRule.DirectionType, quantity, materialRule.FacilityId, materialRule.Sort, materialRule.Description);
                    materialAsks.Add(materialAsk);
                }
                //工单参数要求
                IList<WorkOrderParameterAsk> parameterAsks = new List<WorkOrderParameterAsk>();
                foreach (SegmentParameterRule parameterRule in processSegment.ParameterRules)
                {
                    WorkOrderParameterAsk parameterAsk = new WorkOrderParameterAsk(parameterRule.Number, parameterRule.Name, parameterRule.RelatedVariableNo, parameterRule.StandardValue, parameterRule.MaxValue, parameterRule.MinValue, parameterRule.ValueUnitNo, parameterRule.FacilityId, parameterRule.Sort, parameterRule.Description);
                    parameterAsks.Add(parameterAsk);
                }

                workOrder.SetPersonAsks(personAsks);
                workOrder.SetEquipmentAsks(equipmentAsks);
                workOrder.SetMaterialAsks(materialAsks);
                workOrder.SetParameterAsks(parameterAsks);
                workOrders.Add(workOrder);
            }

            return workOrders;
        }
        #endregion
    }
}
